package com.tech.distribute_lock.redis.redisson;

import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author litianlin
 * @date 2023/12/4 18:02
 * @description:
 */
@RestController
@RequestMapping("/redisson")
public class RedissonController {
    @Autowired
    RedissonClient redisson;

    @Autowired
    RedisTemplate redisTemplate;

    @ResponseBody// 可重入锁
    @GetMapping("/hello")
    public String hello() {
        // 1.获取一把锁，只要锁的名字一样，就是同一把锁
        RLock lock = redisson.getLock("my-lock");
        lock.lock(); // 阻塞式等待。默认加的锁是30s时间
        try {
            // 1、锁的自动续期，运行期间自动给锁续上新的30s，无需担心业务时间长，锁过期会自动被释放
            // 2、加锁的业务只要运行完成，就不会给当前锁续期，即使不手动释放锁，锁默认在30s后自动释放，避免死锁
            System.out.println("加锁成功，执行业务代码..."+Thread.currentThread().getId());
            Thread.sleep(30000);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            System.out.println("释放锁..."+Thread.currentThread().getId());
            lock.unlock();
        }
        return "Hello!";
    }

    @ResponseBody
    @GetMapping("/write")
    public String writeValue(){
        RReadWriteLock lock = redisson.getReadWriteLock("rw-lock");
        RLock rLock = lock.writeLock();
        String s = "";
        try {
            s = UUID.randomUUID().toString();
            // 模拟业务时间
            Thread.sleep(30000);
        } catch (Exception e){

        }finally {
            rLock.unlock();
        }
        redisTemplate.opsForValue().set("writeValue",s);
        return s;
    }

    @GetMapping(value = "/read")
    @ResponseBody
    public String readValue() {
        String s = "";
        RReadWriteLock readWriteLock = redisson.getReadWriteLock("rw-lock");
        //加读锁
        RLock rLock = readWriteLock.readLock();
        try {
            rLock.lock();
            s = (String) redisTemplate.opsForValue().get("writeValue");

            TimeUnit.SECONDS.sleep(10);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            rLock.unlock();
        }
        return s;
    }

    @GetMapping(value = "/park")
    @ResponseBody
    public String park() {
        RSemaphore park = redisson.getSemaphore("park");
        try {
            park.acquire();// 获取一个信号量（redis中信号量值-1）,如果redis中信号量为0了，则在这里阻塞住，直到信号量大于0，可以拿到信号量，才会继续执行。
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return "ok";
    }

    @GetMapping(value = "/go")
    @ResponseBody
    public String go() {
        RSemaphore park = redisson.getSemaphore("park");
        park.release();  //释放一个信号量（redis中信号量值+1）
        return "ok";
    }

    @GetMapping(value = "/lockDoor")
    @ResponseBody
    public String lockDoor() throws InterruptedException {
        RCountDownLatch lockDoor = redisson.getCountDownLatch("lockDoor");
        lockDoor.trySetCount(5); // 设置计数为5
        lockDoor.await(); //等待闭锁完成
        return "放假啦...";
    }

    @GetMapping(value = "/go/{id}")
    public String go(@PathVariable("id") Integer id)  {
        RCountDownLatch lockDoor = redisson.getCountDownLatch("lockDoor");
        lockDoor.countDown(); // 计数减1
        return id+"班都走光了";
    }
}
